/*
 * Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Eclipse Public License
 * Version 1.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://opensource.org/licenses/EPL-1.0 and read it before using this file.
 */

#include "plugin_model_impl_common.h"


void drawRect( HDC hdc, long left, long top, long right, long bottom )
{
    RECT r = { left, top, right, bottom };

    //HGDIOBJ hpen = CreatePen( PS_DASH, 1, RGB( 128, 128, 128 ) );
    HGDIOBJ hpen = ::CreatePen( PS_DOT, 1, RGB( 0, 0, 0 ) );

    HGDIOBJ hgdiobj1 = ::SelectObject( hdc, hpen );
    HGDIOBJ hgdiobj2 = ::SelectObject( hdc, ::GetStockObject( NULL_BRUSH ) );

    ::Rectangle( hdc, r.left, r.top, r.right, r.bottom );

    ::SelectObject( hdc, hgdiobj1 );
    ::SelectObject( hdc, hgdiobj2 );
    ::DeleteObject( hpen );
}

void _PluginModel::renderBuffer( HDC hdc )
{
    if ( this->hasImage() )
    {
        if ( m_hRenderBitmap )
        {
            ::DeleteObject( m_hRenderBitmap );
            m_hRenderBitmap = NULL;
        }

        {
            byte_t* tmp = m_renderDib;

            bool result = ::resizeImageNearest( ( BITMAPINFOHEADER** ) &m_renderDib, m_renderDibSize, m_viewPortionRect.left, m_viewPortionRect.top, m_viewPortionRect.width, m_viewPortionRect.height, ( double ) m_zoomFactor, m_activeImage->getPixels() );

            if ( result )
            {
                BITMAPINFOHEADER* destBih = ( BITMAPINFOHEADER* ) m_renderDib;

                //HDC hdc1 = ::GetDC( NULL );
                //HDC hdc1 = hdc;

                m_hRenderBitmap = ::CreateDIBitmap( hdc, destBih, CBM_INIT, Dib::GetBits( destBih ), ( BITMAPINFO* ) m_renderDib, DIB_RGB_COLORS );

                //::ReleaseDC( NULL, hdc1 );
            }
        }

        m_activeImage->unlock(); // unlock the image

        m_refresh = false;
    }
}

void _PluginModel::drawCropRect( HDC hdc, Point& p, Size& s )
{
    int left = p.x, top = p.y, 
        right = p.x + s.width, bottom = p.y + s.height, 
        width = s.width, height = s.height;
    int right1 = right + 1, bottom1 = bottom + 1;

    int size = 8;
    int xh = left + ( ( width - size ) >> 1 ), yh = top + ( ( height - size ) >> 1 ),
        xhs = xh + size, yhs = yh + size,
        lefts = left + size, tops = top + size, rights = right1 - size, bottoms = bottom1 - size;

    HGDIOBJ hpen = ::CreatePen( PS_DOT, 1, RGB( 0, 0, 0 ) );

    HGDIOBJ hgdiobj1 = ::SelectObject( hdc, hpen );
    HGDIOBJ hgdiobj2 = ::SelectObject( hdc, ::GetStockObject( NULL_BRUSH ) );

    int oldRop = ::SetROP2( hdc, R2_NOTXORPEN ); //R2_NOT

    //Rectangle( hdc, left, top, right, bottom );

    // rubber band
    auto drawLine = [hdc]( int x1, int y1, int x2, int y2 )
    {
        ::MoveToEx( hdc, x1, y1, NULL );
        ::LineTo( hdc, x2, y2 );
    };
    // top
    drawLine( lefts, top, xh, top );
    drawLine( xhs, top, rights, top );
    // right
    drawLine( right, tops, right, yh );
    drawLine( right, yhs, right, bottoms );
    // bottom
    drawLine( lefts, bottom, xh, bottom );
    drawLine( xhs, bottom, rights, bottom );
    // left
    drawLine( left, tops, left, yh );
    drawLine( left, yhs, left, bottoms );


    // markers

    ::SelectObject( hdc, ::GetStockObject( BLACK_PEN ) );

    // corners
    ::Rectangle( hdc, left, top, lefts, tops );
    ::Rectangle( hdc, rights, top, right1, tops );
    ::Rectangle( hdc, rights, bottoms, right1, bottom1 );
    ::Rectangle( hdc, left, bottoms, lefts, bottom1 );

    // sides
    ::Rectangle( hdc, xh, top, xhs, tops );
    ::Rectangle( hdc, rights, yh, right1, yhs );
    ::Rectangle( hdc, xh, bottoms, xhs, bottom1 );
    ::Rectangle( hdc, left, yh, lefts, yhs );

    ::SetROP2( hdc, oldRop );

    //SelectObject( hdc, GetStockObject( WHITE_BRUSH ) );

    //SelectObject( hdc, hgdiobj1 );
    //SelectObject( hdc, hgdiobj2 );
    ::DeleteObject( hpen );
}

void _PluginModel::render( HDC hdc )
{
    if ( this->hasImage() )
    {
        if ( !m_hdc )
        {
            m_hdc = ::CreateCompatibleDC( NULL );
        }

        //if ( m_refresh )
        renderBuffer( hdc );

        //m_updateBounds = true;

        if ( m_mouseZooming )
        {
            int oldRop = ::SetROP2( hdc, R2_NOTXORPEN ); //R2_NOT

            if( m_mouseRectInitialized )
            {
                ::drawRect( hdc, m_mouseStartPos.x, m_mouseStartPos.y, m_mousePos.x, m_mousePos.y );
            }

            ::drawRect( hdc, m_mouseStartPos.x, m_mouseStartPos.y, m_mouseTopPos.x, m_mouseTopPos.y );

            ::SetROP2( hdc, oldRop );

            ::ReleaseDC( NULL, hdc );

            m_mousePos.x = m_mouseTopPos.x;
            m_mousePos.y = m_mouseTopPos.y;

            m_mouseRectInitialized = true;

            m_mouseZooming = false;

            return;
        }

        HGDIOBJ gdiobj = ::SelectObject( m_hdc, m_hRenderBitmap );

        //::BitBlt( hdc, m_viewPortionRect.left, m_viewPortionRect.top, m_viewPortionRect.width, m_viewPortionRect.height, m_hdc, 0, 0, SRCCOPY );
        ::BitBlt( hdc, m_viewPortionPos.x, m_viewPortionPos.y, m_viewPortionRect.width, m_viewPortionRect.height, m_hdc, 0, 0, SRCCOPY );

        // draw background
        HGDIOBJ gdiobj1 = ::SelectObject( hdc, GetStockPen( WHITE_PEN ) );
        HGDIOBJ gdiobj2 = ::SelectObject( hdc, GetStockBrush( WHITE_BRUSH ) );

        if ( m_viewPortionPos.x > 0 )
        {
            ::Rectangle( hdc, 0, 0, m_viewPortionPos.x, m_viewportSize.height );
            ::Rectangle( hdc, m_viewPortionPos.x + m_viewPortionRect.width, 0, m_viewportSize.width, m_viewportSize.height );
        }
        else if ( m_viewPortionPos.y > 0 )
        {
            ::Rectangle( hdc, 0, 0, m_viewportSize.width, m_viewPortionPos.y );
            ::Rectangle( hdc, 0, m_viewPortionPos.y + m_viewPortionRect.height, m_viewportSize.width, m_viewportSize.height );
        }

        // crop rectangle
        if ( m_cropState && m_cropRectDefined )
        {
            drawCropRect( hdc, m_cropRectWindowPos, m_cropRectSize );
        }

        // cleanup
        //DeleteObject( gdiobj1 );
        //DeleteObject( gdiobj2 );

        ::DeleteDC( m_hdc );
        m_hdc = NULL;
    }
    else
    {
        HGDIOBJ gdiobj1 = ::SelectObject( hdc, GetStockPen( WHITE_PEN ) );
        HGDIOBJ gdiobj2 = ::SelectObject( hdc, GetStockBrush( WHITE_BRUSH ) );

        ::Rectangle( hdc, 0, 0, m_viewportSize.width, m_viewportSize.height );

        ::DeleteObject( gdiobj1 );
        ::DeleteObject( gdiobj2 );
    }

    //m_hdc = NULL;
}
